package org.pfc.porlapatilla.repositories;

import java.util.List;

import org.pfc.porlapatilla.model.Product;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.Point;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

/**
 * This Repository provides data access to ProductService.
 * 
 * @author jorgepolobermudez
 * 
 */
public interface ProductRepository extends MongoRepository<Product, String> {

    /**
     * Find a product by id.
     * 
     * @param id
     *            The product id.
     * @return The found product.
     */
    Product findById(String id);

    /**
     * Find a product list by title.
     * 
     * @param title
     *            The product title.
     * @return The list of found products.
     */
    List<Product> findByTitle(String title);

    /**
     * Find a product page by title.
     * 
     * @param title
     *            The product title.
     * @param pageable
     *            The page access data.
     * @return The page of found products.
     */
    Page<Product> findByTitle(String title, Pageable pageable);

    /**
     * Find a product list by title regex.
     * 
     * @param title
     *            The product title regex.
     * @return The list of found products.
     */
    List<Product> findByTitleRegex(String title);

    /**
     * Find a product page by title regex.
     * 
     * @param title
     *            The product title regex.
     * @param pageable
     *            The page access data.
     * @return The page of found products.
     */
    Page<Product> findByTitleRegex(String title, Pageable pageable);

    /**
     * Find a product list by subcategory.
     * 
     * @param subcategory
     *            The product subcategory.
     * @return The list of found products.
     */
    List<Product> findBySubcategory(String subcategory);

    /**
     * Find a product page by subcategory.
     * 
     * @param subcategory
     *            The product subcategory.
     * @param pageable
     *            The page access data.
     * @return The page of found products.
     */
    Page<Product> findBySubcategory(String subcategory, Pageable pageable);

    /**
     * Find a products list when the distance from a origin point is less than
     * distance parameter.
     * 
     * @param point
     *            The origin point.
     * @param distance
     *            The distance.
     * @return The page of found products.
     */
    List<Product> findByLocationNear(Point point, Distance distance);

    /**
     * Find a products page when the distance from a origin point is less than
     * distance parameter.
     * 
     * @param point
     *            The origin point.
     * @param distance
     *            The distance.
     * @param pageable
     *            The page access data.
     * @return The page of found products.
     */
    Page<Product> findByLocationNear(Point point, Distance distance,
	    Pageable pageable);

    /**
     * Find a product list by status.
     * 
     * @param state
     *            The product status.
     * @return The list of found products.
     */
    @Query(value = "{ 'status' : ?0 }", fields = "{'title' : 1, 'status' : 1, 'address':{'city' : 1}, 'publicationDate' : 1}")
    List<Product> findByStatus(String status);

    /**
     * Find a product page by status.
     * 
     * @param state
     *            The product status.
     * @param pageable
     *            The page access data.
     * @return The page of found products.
     */
    Page<Product> findByStatus(String status, Pageable pageable);

    /**
     * Find a product list by provider id.
     * 
     * @param providerId
     *            The product provider id.
     * @return The list of found products.
     */
    @Query("{ 'provider': { '$ref': 'user', '$id': { '$oid': ?0 } } }")
    Page<Product> findByProviderId(String providerId, Pageable pageable);
}
